//----------------------------------Include-------------------------------------
#include "mcu.h"
#include "glbvar.h"
//------------------------------------------------------------------------------

//普通通道：ADC_IN0~11
//温度传感器和通道 ADC_IN12 相连接
//VREFINT 和通道 ADC_IN13 相连接
//VREFP 和 ADC_IN14 相连接
//VDDA和通道 ADC_IN15 相连接
//OPAMP_OUT 输出和通道 ADC_IN6 相连接
//ADC 内部通道可以按规则或者注入通道的方式进行转换

//-----------------------------------Macro--------------------------------------
#define _ADC_INST           ADC
//------------------------------------------------------------------------------
#define _DMA_INST           DMA
#define _DMA_EN             1
#define _DMA_CHN            DMA_CH5
#define _DMA_NUM            5
//------------------------------------------------------------------------------
#define _SAMP_LEN           128
#define _ADC_VREF           (3.3)
//------------------------------------------------------------------------------
#define _CHN_N              (1)
//------------------------------------------------------------------------------

//--------------------------------Static Var------------------------------------
static uint16_t             nau16_ad_cache[_SAMP_LEN];
static uint16_t             nu16_temp;
//------------------------------------------------------------------------------

//--------------------------------Static Func-----------------------------------
#define V25        1.32f    /*V25 is the voltage value at 25 degree Celsius by datasheet define*/
#define AVG_SLOPE  0.004f   /*xx mv per degree Celsius  by datasheet define*/
static float _TempCal(uint16_t TempAdVal)
{
  float Temperate,tempValue;
  tempValue=TempAdVal*(3.3/4096);             /* Voltage value of temperature sensor */
  Temperate=(V25-tempValue)/AVG_SLOPE+25.0f;  /* Get the temperature inside the chip */
  return Temperate;
}

static uint16_t _average(volatile uint16_t * p, uint32_t n)
{ 
  uint32_t i, sum=0;
  for(i=0; i<n; i++){
    sum += p[i];
  }
  return sum/n;
}
//------------------------------------------------------------------------------

//--------------------------------Public Func-----------------------------------
float mcu_get_temp(void)
{
  return _TempCal(nu16_temp);
}
//------------------------------------------------------------------------------
void mcu_init_adc(void)
{
//periph clock
  RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC, ENABLE);
  
//pin
  
//adc
  RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSI, RCC_ADC1MCLK_DIV8);
  ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV16);
  
  //common
  ADC_InitType      ADC_InitS;
  ADC_InitStruct  (&ADC_InitS);
  
  ADC_InitS.MultiChEn      = DISABLE;   //scan
  ADC_InitS.ContinueConvEn = DISABLE;   //continuous
  ADC_InitS.ExtTrigSelect  = ADC_EXT_TRIGCONV_T3_TRGO;
  ADC_InitS.DatAlign       = ADC_DAT_ALIGN_R;
  ADC_InitS.ChsNumber      = 1;
  ADC_Init(_ADC_INST, &ADC_InitS);
  
  ADC_EnableExternalTrigConv(_ADC_INST, ENABLE);
  ADC_EnableTempSensor(ENABLE);
  
  //channel
  ADC_ConfigRegularChannel(_ADC_INST, ADC_CH_12, 1, ADC_SAMP_TIME_300CYCLES5);
  
  //enable
  ADC_Enable(_ADC_INST, ENABLE);
  while(!ADC_GetFlagStatusNew(_ADC_INST, ADC_FLAG_RDY));
  while(ADC_GetFlagStatusNew(_ADC_INST, ADC_FLAG_PD_RDY));
      
#if _DMA_EN == 1
  ADC_EnableDMA(_ADC_INST, ENABLE);
  
  //periph clock
  RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA, ENABLE);

  //dma
  DMA_InitType      DMA_InitS;
  DMA_StructInit  (&DMA_InitS);
  
  DMA_DeInit(_DMA_CHN);
  DMA_InitS.PeriphAddr     = (uint32_t)&_ADC_INST->DAT;
  DMA_InitS.MemAddr        = (uint32_t)nau16_ad_cache;
  DMA_InitS.Direction      = DMA_DIR_PERIPH_SRC;
  DMA_InitS.BufSize        = 0;
  DMA_InitS.PeriphInc      = DMA_PERIPH_INC_DISABLE;
  DMA_InitS.DMA_MemoryInc  = DMA_MEM_INC_ENABLE;
  DMA_InitS.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD;
  DMA_InitS.MemDataSize    = DMA_MemoryDataSize_HalfWord;
  DMA_InitS.CircularMode   = DMA_MODE_CIRCULAR;
  DMA_InitS.Priority       = DMA_PRIORITY_HIGH;
  DMA_InitS.Mem2Mem        = DMA_M2M_DISABLE;
  DMA_Init(_DMA_CHN, &DMA_InitS);
  
  //trigger
  DMA_RequestRemap(DMA_REMAP_ADC, _DMA_INST, _DMA_CHN, ENABLE);
  
  //interrupt
  DMA_ConfigInt(_DMA_CHN, DMA_INT_TXC, ENABLE);
  //NVIC
  NVIC_InitType    NVIC_InitS_DMATx;
  NVIC_InitS_DMATx.NVIC_IRQChannel         = DMA_Channel5_IRQn;
  NVIC_InitS_DMATx.NVIC_IRQChannelPriority = 0;
  NVIC_InitS_DMATx.NVIC_IRQChannelCmd      = ENABLE;
  NVIC_Init(&NVIC_InitS_DMATx);
  
//enable
  _DMA_INST->INTCLR = 0x0F<<((_DMA_NUM-1)*3);   //clear all flag
  DMA_SetCurrDataCounter(_DMA_CHN, _SAMP_LEN);
  DMA_EnableChannel(_DMA_CHN, ENABLE);
#endif
}
//------------------------------------------------------------------------------

//------------------------------------ISR---------------------------------------
void DMA_Channel5_IRQHandler(void)
{
  if(_DMA_INST->INTSTS & (1<<((_DMA_NUM-1)*4+1)) ){   //DMA_GetIntStatus(DMA_INT_TXC1)
    _DMA_INST->INTCLR  = (1<<((_DMA_NUM-1)*4+1));     //DMA_ClrIntPendingBit(DMA_INT_TXC1)
    
    nu16_temp = _average(nau16_ad_cache, _SAMP_LEN);
  }
  
  if(_DMA_INST->INTSTS & (1<<((_DMA_NUM-1)*4+3)) ){   //err
    _DMA_INST->INTCLR  = (1<<((_DMA_NUM-1)*4+3));
  }
}
//------------------------------------EOF---------------------------------------







